package gofish.dao;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import gofish.objects.Game;

/**
 * http://www.daemonology.net/blog/2008-06-29-high-performance-simpledb.html
 * http://docs.oracle.com/javase/tutorial/networking/sockets/index.html
 * http://aws.amazon.com/articles/1394?_encoding=UTF8&jiveRedirect=1
 * 
 * @author Kylyn
 *
 */

public class GoFishDAOHandler {
	
	private final String[] PLAYING_CARDS = {"AH", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "TH", "JH", "QH", "KH",
			"AD", "2D", "3D", "4D", "5D", "6D", "7D", "8D", "9D", "TD", "JD", "QD", "KD",
			"AC", "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "TC", "JC", "QC", "KC",
			"AS", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "TS", "JS", "QS", "KS",};
	
	private GoFishDAO data;
	
	public GoFishDAOHandler() {
		data = new GoFishDAO();
	}
	
	/**
	 * Connect to database.
	 * @throws DAOException
	 */
	public void connect() throws DAOException {
		data.connect();
	}
	
	/**
	 * Disconnect from database.
	 * @throws DAOException
	 */
	public void disconnect() throws DAOException {
		data.disconnect();
	}
	
	/**
	 * Get all logged in users.
	 * @param group
	 * @return
	 */
	public String[] getLoggedInUsers(int group) {
//		return data.getUsers(true);
		return getGroupMembers(group);
	}
	
	/**
	 * Check if user exists.
	 * @param username
	 * @return
	 */
	public boolean userExists(String username) {
		return !data.getUserLoggedIn(username).equals("");
	}
	
	/**
	 * Check if user logged in.
	 * @param username
	 * @return
	 */
	public boolean userLoggedIn(String username) {
		return data.getUserLoggedIn(username).equals("true");
	}
	
	/**
	 * Login user.
	 * @param username
	 * @return
	 */
	public boolean loginUser(String username) {
		// if username is not logged in
		// add username to user table with logged_in=true
		// and return true
		// otherwise return false
		data.loginUser(username);
		return true;
	}
	
	/**
	 * Logout user.
	 * @param username
	 * @return
	 */
	public boolean logoutUser(String username) {
		// if username is logged in
		// remove username from user table
		// and return true
		// otherwise return false
		data.logoutUser(username);
		return true;
	}
	
	/**
	 * Generate unique group ID. Add group ID to game table
	 * with e_id=0 and turn_id=0.
	 * @param username
	 * @return group
	 */
	public int createGroup(String username) {
		int group = 1;
		data.addGroup(group, 0, 0);
		return group;
	}
	
	/**
	 * Get list of players in group.
	 * @param group
	 * @return
	 */
	public String[] getGroupMembers(int group) {
		return data.getGroupMembers(group);
	}
	
	/**
	 * Get the event ID of group.
	 * @param group
	 * @return
	 */
	public int getEventID(int group) {
		return data.getEventID(group);
	}
	
	/**
	 * Increment the event ID of group.
	 * @param group
	 */
	public void incrementEventID(int group) {
		int e_id = data.getEventID(group) + 1;
		data.setEventID(group, e_id);
	}
	
	/**
	 * Update event ID for group to -1. Generate
	 * game deck. Deal player hands. If number of players
	 * if less than 5, deal 7 cards each. Otherwise, 
	 * deal 5 cards each.
	 * @param group
	 * @return
	 */
	public boolean startGame(int group) {
		// update e_id with group to -1
		data.setEventID(group, -1);
		// generate game deck
		List<String> deck = new LinkedList<String>();
		for (int i = 0; i < PLAYING_CARDS.length; i++) {
			deck.add(PLAYING_CARDS[i]);
		}
		shuffleDeck(deck);
		// get number of players
		String[] players = data.getGroupMembers(group);
		
		int handSize = 0;
		// if num players less than 5
		if (players.length < 5) {
			// deal each player 7 cards
			handSize = 7;
			
		} else {
			// otherwise deal each player 5 cards
			handSize = 5;
		}
		
		int currPos = 0;
		for (int i = 0; i < players.length; i++) {
			List<String> hand = new LinkedList<String>();
			currPos = i * handSize;
			hand.addAll(deck.subList(currPos, currPos + (handSize - 1)));
			data.setPlayerHand(players[i], hand);
		}
		// put remainder of cards in game_deck
		List<String> gameDeck = new LinkedList<String>();
		gameDeck.addAll(deck.subList(currPos + handSize, deck.size() - 1));
		data.addGameDeck(group, gameDeck);
		// if all steps completed
		// return true
		// otherwise return false
		return true;
	}
	
	/**
	 * Shuffle deck of "cards".
	 * @param deck
	 * @return
	 */
	private void shuffleDeck(List<String> deck) {
		Collections.shuffle(deck);
	}
	
	/**
	 * Shuffle deck of game.
	 * @param group
	 */
	public void shuffleDeck(int group) {
		List<String> deck = data.removeGameDeck(group);
		shuffleDeck(deck);
		data.addGameDeck(group, deck);
	}
	
//	/**
//	 * Set hand for player username.
//	 * @param username
//	 * @param cards
//	 */
//	private void setPlayerHand(String username, String[] cards) {
//		// put cards in player_hand for username
//	}
	
//	/**
//	 * Set deck for group.
//	 * @param group
//	 */
//	private void setGameDeck(int group, String[] deck) {
//		
//	}
	
	/**
	 * Update turn_id for game.
	 * @param group
	 */
	public void nextTurn(int group) {
		int turn_id = data.getGameTurnID(group) + 1;
		int numPlayers = data.getGroupMembers(group).length;
		if (turn_id >= numPlayers) {
			turn_id = 0;
		}
		data.setGameTurnID(group, turn_id);
	}
	
	/**
	 * Get the current state of the game.
	 * @param group
	 * @return
	 */
	public Game getGameState(int group) {
		return null;
	}
	
	/**
	 * Checks if card is in player's hand.
	 * @param group
	 * @param username
	 * @param card
	 * @return
	 */
	public boolean isCardInPlayerHand(int group, String username, String card) {
		return false;
	}
	
//	public void exchangeCard(int group, String player, String target, String card) {
//		
//	}
	
	/**
	 * Checks if player's hand is empty.
	 * @param group
	 * @param username
	 * @return
	 */
	public boolean isPlayerHandEmpty(int group, String username) {
		int handSize = getPlayerHandSize(username);
		return (handSize == 0);
	}
	
	private int getPlayerHandSize(String username) {
		return data.getPlayerHandSize(username);
	}
	
	/**
	 * Checks if deck of game is empty.
	 * @param group
	 * @return
	 */
	public boolean isDeckEmpty(int group) {
		int deckSize = getGameDeckSize(group);
		return (deckSize == 0);
	}
	
	private int getGameDeckSize(int group) {
		return data.getGameDeckSize(group);
	}
	
	/**
	 * Get card from top of deck of game.
	 * @param group
	 * @return
	 */
	public String goFish(int group) {
		String card = data.removeTopCardFromDeck(group);
		return card;
	}
	
	public void removeCardFromPlayerHand(int group, String username, String card) {
		data.removeCardFromPlayerHand(username, card);
	}
	
	public void addCardToPlayerHand(int group, String username, String card) {
		data.addCardToPlayerHand(username, card);
	}
	
	public void addCardToPlayerPairs(int group, String username, String card) {
		data.addCardToPlayerPairs(username, card);
	}
	
	public void leaveGame() {
		
	}
	
	public void endGame(int group) {
		// set eid to -2 for game
	}

}
